package com.nulstudio.emotion.text.service;

import com.alibaba.fastjson2.JSONObject;
import com.nulstudio.emotion.text.config.NulSecurityConfig;
import com.nulstudio.emotion.text.entity.NulTextEntry;
import com.nulstudio.emotion.text.entity.NulUserDetail;
import com.nulstudio.emotion.text.exception.NulException;
import com.nulstudio.emotion.text.exception.NulExceptionConstants;
import com.nulstudio.emotion.text.mapper.TextRecognitionMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.ArrayList;
import java.util.List;

@Service
public final class TextRecognitionService {

    @Value("${model.url}")
    private String modelUrl;

    @NonNull
    private final TextRecognitionMapper textRecognitionMapper;

    public TextRecognitionService(@NonNull TextRecognitionMapper textRecognitionMapper) {
        this.textRecognitionMapper = textRecognitionMapper;
    }

    @NonNull
    public List<Boolean> analyzeStrings(@NonNull List<String> strings) throws NulException {
        final WebClient webClient = WebClient.builder().baseUrl(modelUrl).build();

        final String requestString = JSONObject.toJSONString(strings);

        final TextRecognitionResult textRecognitionResult = webClient.post()
                .bodyValue(requestString)
                .retrieve()
                .bodyToMono(TextRecognitionResult.class)
                .block();

        if (textRecognitionResult == null) {
            throw new NulException(NulExceptionConstants.MODEL_LOAD_ERROR);
        }

        final List<Boolean> result = textRecognitionResult.getData();
        final NulUserDetail userDetail = NulSecurityConfig.getContextUserDetail();
        final int uid = userDetail.getUid();

        final List<NulTextEntry> histories = new ArrayList<>();

        for (int i = 0; i < strings.size(); ++i) {
            histories.add(new NulTextEntry(strings.get(i), result.get(i)));
        }

        histories.forEach(textRecognitionMapper::insertHistory);
        textRecognitionMapper.insertUidHistoriesMap(uid, histories);

        return result;
    }

    @NonNull
    public List<NulTextEntry> getHistories(int uid, @NonNull String filter) {
        return textRecognitionMapper.getHistories(uid, "%" + filter + "%");
    }

    @NonNull
    public List<NulTextEntry> getCurrentUserHistories(@NonNull String filter) {
        final NulUserDetail userDetail = NulSecurityConfig.getContextUserDetail();
        final int uid = userDetail.getUid();
        return getHistories(uid, filter);
    }

    public void deleteHistory(int id) throws NulException {
        final NulUserDetail userDetail = NulSecurityConfig.getContextUserDetail();
        final int uid = userDetail.getUid();
        final Integer ownerUid = textRecognitionMapper.selectHistoryUidById(id);

        if (ownerUid == null || ownerUid != uid) {
            throw new NulException(NulExceptionConstants.INVALID_DELETE_HISTORY_REQUEST);
        }

        textRecognitionMapper.deleteHistory(id);
    }

    private static class TextRecognitionResult {
        @NonNull
        private List<Boolean> data = new ArrayList<>();

        @NonNull
        public List<Boolean> getData() {
            return data;
        }

        public void setData(@NonNull List<Boolean> data) {
            this.data = data;
        }
    }

}
